package com.ruoyi.quartz.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.Func;
import com.ruoyi.extdata.domain.SmsData;
import com.ruoyi.sms.domain.SmsSendData;
import com.ruoyi.sms.service.ISmsService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.stream.Collectors;

/**
 * 批量任务
 *
 * @author ruoyi
 */
@Slf4j
@Component
@AllArgsConstructor
public class ReCallTask {

    private ISmsRecallService smsRecallService;

    private ISmsService smsService;

    private IAppUserService appUserService;

    private IRealNameAuthService realNameAuthService;

    private ISmsTemplateService templateService;

    private ISmsTaskService smsTaskService;

    public static String PARAM_MARK = "#";

    /**
     * 限制最大开启线程数
     */
    private static Semaphore semaphore = new Semaphore(20);

    /**
     * 提现，实名失败，授信失败
     */
    private static List<String> excludeList = Arrays.asList(UserConstants.RECALL_LOAN, UserConstants.RECALL_CREDIT_SUBMITTED, UserConstants.RECALL_KYS_SUBMITTED);

    public void recallTask() {
        log.info("短信召回任务 Start>>>>>>>>>>");

        List<SmsRecall> smsRecalls = smsRecallService.selectSmsRecallList(new SmsRecall()).stream().filter(e -> !excludeList.contains(e.getFirstApplyType())).collect(Collectors.toList());
        SmsTemplate smsTemplateQ = new SmsTemplate();
        smsTemplateQ.setNoticeType(BizConstants.SMS_NOTICE_TYPE_RECALL);
        Map<String, List<SmsTemplate>> templateMap = templateService.selectSmsTemplateList(smsTemplateQ).stream().collect(Collectors.groupingBy(SmsTemplate::getSmsType));

        ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
        //获取需要执行的任务
        smsRecalls.stream().filter(e ->
                //根据type匹配模版，再判断firstTime是否在模版的触发时限内
                Func.isNotEmpty(templateMap.get(e.getFirstApplyType()))
        ).forEach(e -> {
            try {
                SmsTemplate smsTemplate = firstTimeCompare(templateMap.get(e.getFirstApplyType()), e, js);
                if (smsTemplate == null) {
                    return;
                }

                AppUser appUser = new AppUser();
                appUser.setUserUuid(e.getUserId());
                List<AppUser> appUsers = appUserService.selectAppUserList(appUser);
                if (appUsers.size() == 0) {
                    throw new BusinessException(RspEnmu.ILLEGAL_USER_REQ_ERR);
                }
                appUser = appUsers.get(0);

                SmsTask smsTask = new SmsTask();
                smsTask.setUserId(e.getUserId());
                smsTask.setCountryCode("+234");
                smsTask.setPhone(appUser.getPhone());
                smsTask.setNoticeType(smsTemplate.getNoticeType());
                smsTask.setSmsType(smsTemplate.getSmsType());
                smsTask.setTemplateId(smsTemplate.getTemplateId());
                smsTask.setContent(smsTemplate.getTemplateContent());

                RealNameAuth realNameAuth = new RealNameAuth();
                realNameAuth.setUserId(e.getUserId());
                List<RealNameAuth> realNameAuths = realNameAuthService.selectRealNameAuthList(realNameAuth);
                JSONObject param = new JSONObject();
                if (realNameAuths.size() > 0) {
                    param.put("lastName", realNameAuths.get(0).getLastName());
                }

                smsTask.setContent(replaceTemplateParams(smsTemplate.getTemplateContent(), param));
                smsTask.setSmsParam(JSON.toJSONString(param));
                addAndAndUp(smsTask, e);

//                System.err.println(templateMap.get(e.getFirstApplyType()).toString());
//                semaphore.acquire();
//                //多模版匹配的情况只执行第一条
//                smsTask smsTask1 = new smsTask(e.getUserId(), smsTemplate);
//                System.err.println("执行线程:" + e);
//                System.err.println("使用模版:" + smsTemplate);
//                new Thread(smsTask1).start();

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
    }

    private boolean addAndAndUp(SmsTask smsTask, SmsRecall recall) {
        recall.setMessageApplyStep(recall.getMessageApplyStep() + 1);
        return smsTaskService.insertSmsTask(smsTask) > 0 && smsRecallService.updateSmsRecall(recall) > 0;

    }

    protected String replaceTemplateParams(String templateContent, JSONObject dataJson) {
        String smsContent = templateContent;

        Iterator<String> iterator = (Iterator<String>) dataJson.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = dataJson.getString(key);
            if (smsContent.contains(key)) {
                smsContent = smsContent.replace(PARAM_MARK + key + PARAM_MARK, value);
            }
        }
        return smsContent;
    }

    private class smsTask implements Runnable {

        String userId;
        SmsTemplate smsTemplate;

        smsTask(String userId, SmsTemplate smsTemplate) {
            this.userId = userId;
            this.smsTemplate = smsTemplate;
        }

        @Override
        public void run() {
            try {
                System.err.println("开始执行线程");
                AppUser appUser = new AppUser();
                appUser.setUserUuid(userId);
                List<AppUser> appUsers = appUserService.selectAppUserList(appUser);
                if (appUsers.size() == 0) {
                    throw new BusinessException(RspEnmu.ILLEGAL_USER_REQ_ERR);
                }
                appUser = appUsers.get(0);
                JSONObject param = new JSONObject();
                RealNameAuth realNameAuth = new RealNameAuth();
                realNameAuth.setUserId(userId);
                List<RealNameAuth> realNameAuths = realNameAuthService.selectRealNameAuthList(realNameAuth);
                if (realNameAuths.size() > 0) {
                    param.put("lastName", realNameAuths.get(0).getLastName());
                }

                SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_RECALL)
                        .phoneNumber(appUser.getPhone()).countryCode(appUser.getCountryCode())
                        .smsParam(param).smsType(smsTemplate.getSmsType()).content(smsTemplate.getTemplateContent()).build();
                System.err.println("短信参数" + smsData.toString());
                smsService.sendSms(smsData);
            } catch (Exception e) {
                log.error("召回短信发送异常，UserId:{},Template:{}", userId, smsTemplate.toString(), e);
            } finally {
                semaphore.release();
            }
        }
    }


    private SmsTemplate firstTimeCompare(List<SmsTemplate> smsRecallTemplates, SmsRecall recall, ScriptEngine js) throws ScriptException {
        if (Func.hasEmpty(smsRecallTemplates, recall.getFirstApplyTime(), js)) {
            return null;
        }
        //倒叙
        for (int i = smsRecallTemplates.size() - 1; i >= 0; i--) {
            double firstT = Func.timeDifferenceOfHour(recall.getFirstApplyTime());
            String[] compares = smsRecallTemplates.get(i).getCompare().replaceAll("N", String.valueOf(firstT)).split(",");
            boolean compare = true;
            for (int j = 0; j < compares.length; j++) {
                //满足条件后不再判断同一任务的其他模版，结束外层当前循环
                if (!(boolean) js.eval(compares[j])) {
                    compare = false;
                }
            }
            if (compare) {
                //比较模版
                SmsTemplate smsTemplate = smsRecallTemplates.get(i);
                Integer step = recall.getMessageApplyStep();
                //注册未实名
                if ("200001".equals(smsTemplate.getTemplateId()) && step == 0) {
                    return smsRecallTemplates.get(i);
                }
                if ("200002".equals(smsTemplate.getTemplateId()) && step == 1) {
                    return smsRecallTemplates.get(i);
                }
                //实名未授信
                if ("200003".equals(smsTemplate.getTemplateId()) && step == 0) {
                    return smsRecallTemplates.get(i);
                }
                if ("200004".equals(smsTemplate.getTemplateId()) && step == 1) {
                    return smsRecallTemplates.get(i);
                }
                //授信未提现
                if ("200005".equals(smsTemplate.getTemplateId()) && step == 0) {
                    return smsRecallTemplates.get(i);
                }
                if ("200006".equals(smsTemplate.getTemplateId()) && step == 1) {
                    return smsRecallTemplates.get(i);
                }

            }
        }
        return null;
    }


}
